#pragma once

#include <iostream>
#include "Sock.hpp"
#include <memory>
#include <sys/select.h>
#include <cstring>
#include <poll.h>

class Pollserver
{
    static const int fd_array_num = 1024;

public:
    Pollserver()
        : sock_ptr_(new Sock)
    {
    }

    void Init(uint16_t port)
    {
        sock_ptr_->Socket();
        sock_ptr_->Bind(port);
        sock_ptr_->Listen();

        for (int i = 0; i < fd_array_num; i++)
        {
            pl_array_[i].fd = -1;
            pl_array_[i].events = 0;
            pl_array_[i].revents = 0;
        }
    }

    void Accept()
    {
        int listen_fd = sock_ptr_->Get_fd();
        struct sockaddr_in client;
        socklen_t len = sizeof(client);
        int sockfd = accept(listen_fd, (sockaddr *)&client, &len);
        if (sockfd < 0)
        {
            Log(Warning) << "accept failed";
        }

        // 将该字段加入到数组中
        // 先找位置
        int pos = 0;
        for (; pos < fd_array_num && pl_array_[pos].fd != -1; pos++)
            ;

        if (pos == fd_array_num)
        {
            Log(Warning) << "fd_array filled";
            close(sockfd);
        }
        else
        {
            pl_array_[pos].fd = sockfd;
            pl_array_[pos].events = POLLIN;
            Log(Info) << "get a connect , sockfd :" << sockfd;
        }
    }

    void Handlerway(int pos)
    {
        int fd_ = pl_array_[pos].fd;

        char buffer[1024];
        memset(buffer, sizeof(buffer), 0);

        int n = read(fd_, buffer, sizeof(buffer) - 1);
        if (n > 0)
        {
            buffer[n] = 0;
            std::string ret = "echo#";
            ret += buffer;
            write(fd_, ret.c_str(), ret.size());
        }
        else if (n == 0)
        {
            pl_array_[pos].fd = -1;
            close(fd_);
        }
        else
        {
            Log(Warning) << "read failed";
            pl_array_[pos].fd = -1;
            close(fd_);
        }
    }

    void Dispenser()
    {
        int listen_fd = sock_ptr_->Get_fd();
        for (int i = 0; i < fd_array_num; i++)
        {
            if (pl_array_[i].fd == -1 || pl_array_[i].revents != POLLIN)
                continue;
            if (pl_array_[i].fd == listen_fd)
            {
                // 可以进行accept
                Accept();
            }
            else
            {
                Handlerway(i);
            }
        }
    }

    void Run()
    {
        int listen_sockfd = sock_ptr_->Get_fd();
        pl_array_[0].fd = listen_sockfd;
        pl_array_[0].events = POLLIN;

        while (1)
        {
            int n = poll(pl_array_, fd_array_num, -1);
            if (n > 0)
            {
                // 有资源就绪，需要进行处理
                Dispenser();
            }
            else if (n == 0)
            {
                // 没有资源就绪
                Log(Info) << "I an waiting for you";
            }
            else
            {
                // 出错
                Log(Warning) << "select fail";
            }
        }
    }

private:
    uint16_t port_;
    std::shared_ptr<Sock> sock_ptr_;
    struct pollfd pl_array_[fd_array_num];
};